// --- Copyright (c) 2006-2008 Stefan Kyntchev ---
// This software is written and copyrighted by Stefan Kyntchev 
// and BeyondPod Team members. All rights are reserved.
// Author contact: support@beyondpod.mobi
// ------------------------------------------------------------------------
// This file is part of BeyondPod RSS Feed Reader and Podcast manager
// (www.codeplex.com/BeyondPod) 
// BeyondPod is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// BeyondPod is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
//  
// You should have received a copy of the GNU General Public License
// along with BeyondPod. If not, see <http://www.gnu.org/licenses/>
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using Microsoft.Win32;
using svs.Mobile.BeyondMedia.UiCore;

namespace svs.Mobile.BeyondMedia.FeedCore
{
	public static class Configuration
	{
		public static readonly string FallBackInstallPath = @"\Program Files";
		private static readonly string m_AppInstallPath;
		private static readonly NameValueCollection m_settings = new NameValueCollection();
		private static readonly string m_settingsPath;
		private static FeedCategory m_ActiveFeedCategory;
		private static TimeSpan? m_GlobalKeepEnclosuresDuration;
		private static int? m_GlobalMaxEnclosures;
		private static int? m_GlobalMaxEnclosuresToOneStepDownload;
		private static int? m_GlobalNumItemsToIncludeInWhatIsNew;
		private static bool m_SettingsChanged;

		static Configuration()
		{
			m_AppInstallPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
			if (m_AppInstallPath.StartsWith(Uri.UriSchemeFile, StringComparison.CurrentCultureIgnoreCase))
				m_AppInstallPath = m_AppInstallPath.Substring(6);

			if (string.IsNullOrEmpty(m_AppInstallPath) || !Directory.Exists(m_AppInstallPath))
			{
				m_AppInstallPath = FallBackInstallPath;
				CoreHelper.WriteLogEntry("Unable to read the default application Install folder!");
			}

			// Get the path of the settings file.
			m_settingsPath = ApplicationInstallPath + @"\Settings.xml";

			if (File.Exists(m_settingsPath))
			{
				try
				{
					var xdoc = new XmlDocument();
					xdoc.Load(m_settingsPath);
					XmlElement root = xdoc.DocumentElement;
					XmlNodeList nodeList = root.ChildNodes.Item(0).ChildNodes;

					// Add settings to the NameValueCollection.
					foreach (XmlNode n in nodeList)
					{
						m_settings.Add(n.Attributes["key"].Value, n.Attributes["value"].Value);
					}
				}
				catch (Exception ex)
				{
					CoreHelper.WriteLogEntry("Unable to read application settings! Reason:" + ex.Message);
				}
			}

			m_SettingsChanged = false;
		}

		public static string LogFilePath
		{
			get { return ApplicationInstallPath + @"\BeyondPodLog.txt"; }
		}

		public static string EnclosureDownloadHistoryFilePath
		{
			get { return ApplicationInstallPath + @"\BeyondPodHistory.bin"; }
		}

		public static string ItemHistoryFilePath
		{
			get { return ApplicationInstallPath + @"\BeyondPodItemHistory.bin"; }
		}

		public static string TraceFilePath
		{
			get { return ApplicationInstallPath + @"\BeyondPodTrace.txt"; }
		}

		public static string FeedUpdateLogFilePath
		{
			get { return ApplicationInstallPath + @"\FeedUpdateLog.htm"; }
		}

		public static Uri HelpFilePath
		{
			get { return new Uri(ApplicationInstallPath + @"\Help\Index.htm", UriKind.Absolute); }
		}

		public static Uri WelcomeFilePath
		{
			get { return new Uri(ApplicationInstallPath + @"\Help\Welcome.htm", UriKind.Absolute); }
		}

		public static string BeyondPodPublicWebSite
		{
			get
			{
				return "http://www.beyondpod.mobi";
			}
		}

		public static Uri VersionCheckURL
		{
			get { return new Uri(BeyondPodPublicWebSite + "/versioncheck.aspx?v=" + ProductVersion, UriKind.Absolute); }
		}

		public static Uri VersionCheckBetaURL
		{
			get
			{
				return new Uri(BeyondPodPublicWebSite + "/BETA/Default.aspx?v=" + ProductVersion, UriKind.Absolute);
			}
		}

		public static DateTime NextNotificationTime
		{
			get
			{
				string value = m_settings.Get("NextNotificationTime");
				if (value == null)
					return DateTime.MinValue;
				try
				{
					return DateTime.ParseExact(value, "r", CultureInfo.InvariantCulture).ToLocalTime();
				}
				catch (Exception Ex)
				{
					CoreHelper.WriteLogEntry("Unable to parse NextNotificationTime setting. Reason:" + Ex.Message);
					return DateTime.MinValue;
				}
			}
			set
			{
				if (NextNotificationTime == value)
					return;

				m_settings.Set("NextNotificationTime", value.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture));
				m_SettingsChanged = true;
			}
		}

		public static Uri AutoVersionCheckURL
		{
			get
			{
				return new Uri(VersionCheckURL + "&t=a", UriKind.Absolute);
			}
		}

		public static string VersionInfoPath
		{
			get
			{
				return Path.Combine(RssCachePath, "VersionInfo.txt");
			}
		}

		public static Uri DonateURL
		{
			get { return new Uri( BeyondPodPublicWebSite + "/Donate/Donate.aspx", UriKind.Absolute); }
		}

		public static Uri SuggestFeatureURL
		{
			get { return new Uri(BeyondPodPublicWebSite + "/SuggestFeature.htm", UriKind.Absolute); }
		}

		public static string ExportedOPMLPath
		{
			get
			{
				string path = m_settings.Get("ExportedOPMLPath") ?? String.Empty;

				if (string.IsNullOrEmpty(path))
					path = ApplicationInstallPath + @"\BeyondPodFeeds.opml";

				return path;
			}
			set
			{
				if (ExportedOPMLPath == value)
					return;

				m_settings.Set("ExportedOPMLPath", value);
				m_SettingsChanged = true;
			}
		}

		public static Version CurrentProductVersion
		{
			get
			{
				return Assembly.GetCallingAssembly().GetName().Version;
			}
		}

		public static string ProductVersion
		{
			get
			{
				return CurrentProductVersion.ToString();
			}
		}

		public static string ApplicationInstallPath
		{
			get { return m_AppInstallPath; }
		}

		public static string RssTemplatesPath
		{
			get { return ApplicationInstallPath + @"\RSSTemplates"; }
		}

		public static string TTSTemplatesPath
		{
			get
			{
				return ApplicationInstallPath + @"\TTSTemplates";
			}
		}

		public static string RssTemplatesImagePath
		{
			get { return RssTemplatesPath + @"\img"; }
		}

		public static string DefaultDownloadPath
		{
			get { return ApplicationInstallPath + @"\Downloads"; }
		}

		public static string RssCachePath
		{
			get
			{
				string path1 = EnclosureDownloadPath + @"\RSSCache";
				if (Directory.Exists(path1))
					return path1;

				return ApplicationInstallPath + @"\RSSCache";
			}
		}

		public static string RssImageCachePath
		{
			get { return RssCachePath + @"\img"; }
		}

		public static string TrackStatePath
		{
			get { return ApplicationInstallPath + @"\TrackState.xml"; }
		}

		/// <summary>
		/// The root path of the feeds tree
		/// </summary>
		public static string EnclosureDownloadPath
		{
			get
			{
				string path = m_settings.Get("FeedRootPath") ?? String.Empty;

				if (path.StartsWith("~"))
					path = path.Replace("~", ApplicationInstallPath);

				return path;
			}
			set
			{
				if (EnclosureDownloadPath == value)
					return;

				m_settings.Set("FeedRootPath", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The the path of last imported OPML
		/// </summary>
		public static string LastImportedOPMLPath
		{
			get
			{
				string path = m_settings.Get("LastImportedOPMLPath");

				if (string.IsNullOrEmpty(path))
					return Path.Combine(ApplicationInstallPath, @"Opml\top100.xml");

				return path;
			}
			set
			{
				if (LastImportedOPMLPath == value)
					return;

				m_settings.Set("LastImportedOPMLPath", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The last track that the user was playing before exiting
		/// </summary>
		public static string LastPlayedTrackPath
		{
			get
			{
				string path = m_settings.Get("LastPlayedTrackPath");
				return path ?? string.Empty;
			}
			set
			{
				if (LastPlayedTrackPath == value)
					return;

				m_settings.Set("LastPlayedTrackPath", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The last screen the user was viewing before exit
		/// </summary>
		public static int LastActiveScreen
		{
			get
			{
				string value = m_settings.Get("LastActiveScreen");
				return value == null ? 0 : int.Parse(value);
			}
			set
			{
				if (LastActiveScreen == value)
					return;

				m_settings.Set("LastActiveScreen", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The short skip interval
		/// </summary>
		public static int ShortSkipInterval
		{
			get
			{
				string value = m_settings.Get("ShortSkipInterval");
				try
				{
					return int.Parse(value);
				}
				catch
				{
					return 5;
				}
			}
			set
			{
				if (ShortSkipInterval == value)
					return;

				m_settings.Set("ShortSkipInterval", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The long skip interval
		/// </summary>
		public static int LongSkipInterval
		{
			get
			{
				string value = m_settings.Get("LongSkipInterval");
				try
				{
					return int.Parse(value);
				}
				catch
				{
					return 30;
				}
			}
			set
			{
				if (LongSkipInterval == value)
					return;

				m_settings.Set("LongSkipInterval", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The On Media End action
		/// </summary>
		public static CoreHelper.MediaEndAction MediaEndAction
		{
			get
			{
				string value = m_settings.Get("MediaEndAction");
				try
				{
					return (CoreHelper.MediaEndAction) (int.Parse(value));
				}
				catch
				{
					return CoreHelper.MediaEndAction.PlayNext;
				}
			}
			set
			{
				if (MediaEndAction == value)
					return;

				m_settings.Set("MediaEndAction", ((int) value).ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The On Media End action
		/// </summary>
		public static PlayerIntegration PlayerIntegration
		{
			get
			{
				string value = m_settings.Get("PlayerIntegration");
				try
				{
					return (PlayerIntegration) (int.Parse(value));
				}
				catch
				{
					return PlayerIntegration.UseInternalPlayer;
				}
			}
			set
			{
				if (PlayerIntegration == value)
					return;

				m_settings.Set("PlayerIntegration", ((int) value).ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the last selected feed.
		/// </summary>
		/// <value>The last selected feed.</value>
		public static Guid LastSelectedFeed
		{
			get
			{
				string id = m_settings.Get("LastSelectedFeed");
				if (string.IsNullOrEmpty(id))
					return Guid.Empty;

				try
				{
					return new Guid(id);
				}
				catch
				{
					return Guid.Empty;
				}
			}
			set
			{
				if (LastSelectedFeed == value)
					return;

				m_settings.Set("LastSelectedFeed", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets if the UI should hide the unsupported file types
		/// </summary>
		public static bool ShowUnsupportedFileTypes
		{
			get
			{
				string value = m_settings.Get("ShowUnsupportedFileTypes");
				if (value == null)
					return true;

				return value == "1" ? true : false;
			}
			set
			{
				if (ShowUnsupportedFileTypes == value)
					return;

				m_settings.Set("ShowUnsupportedFileTypes", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}


		/// <summary>
		/// True if we can connect over EDGE/GPRS/3G connection
		/// </summary>
		public static bool AllowCellularConnections
		{
			get
			{
				string value = m_settings.Get("AllowCellularConnections");
				if (value == null)
					return true;

				return value == "1" ? true : false;
			}
			set
			{
				if (AllowCellularConnections == value)
					return;

				m_settings.Set("AllowCellularConnections", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets if the screen transitions between views are enabled
		/// </summary>
		public static bool EnableScreenTransitions
		{
			get
			{
				string value = m_settings.Get("EnableScreenTransitions");
				if (value == null)
				{
					//ByDefault turn on thersitions for PocketPCs only
					 return PlatformDetection.IsPocketPC();
				}

				return value == "1" ? true : false;
			}
			set
			{
				if (EnableScreenTransitions == value)
					return;

				m_settings.Set("EnableScreenTransitions", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// True if by default All podcasts ina given category are shown in the podcast view (vs. only the selected feed podcats)
		/// </summary>
		public static bool ShowAllPodcastsInCategory
		{
			get
			{
				string value = m_settings.Get("ShowAllPodcastsInCategory");
				if (value == null)
					return false;

				return value == "1" ? true : false;
			}
			set
			{
				if (ShowAllPodcastsInCategory == value)
					return;

				m_settings.Set("ShowAllPodcastsInCategory", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the file types that will be used by the internal player
		/// </summary>
		/// <value>The last of comma separated file extensios.</value>
		public static string InternalPlayerSupportedFileExtensions
		{
			get
			{
				string path = m_settings.Get("InternalPlayerSupportedFileTypes");
				if (path == null)
				{
					path =
						".asf,.asx,.avi,.wav,.wax,.wma,.wm,.avi,.m3u,.mp2v,.mpg,.mpeg,.m1v,.mp2,.mp3,.m3u,.mpa,.mpe,.mpv2,.wmv,.mid,.midi,.rmi,.aif,.aifc,.aiff,.au,.snd,.ivf,.wmz,.wms,.avi,.mov,.qt";
					m_settings.Set("InternalPlayerSupportedFileTypes", path);
					m_SettingsChanged = true;
				}
				return path;
			}
			set
			{
				if (InternalPlayerSupportedFileExtensions == value)
					return;

				if (value == null)
					value = string.Empty;

				m_settings.Set("InternalPlayerSupportedFileTypes",
				               value.Trim().Replace(" ", String.Empty).Replace("..", ".").Replace(".,", ","));
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the shortcut keys.
		/// </summary>
		/// <value>The last selected feed.</value>
		public static string ShortcutKeys
		{
			get
			{
				string path = m_settings.Get("ShortcutKeys");
				if (path == null)
					return string.Empty;

				return path;
			}
			set
			{
				if (ShortcutKeys == value)
					return;

				m_settings.Set("ShortcutKeys", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Prefix for the feed item link. (use it to set a "www.skweezer.net" type url)
		/// </summary>
		public static string LinkPrefix
		{
			get
			{
				string path = m_settings.Get("FeedItemLinkPrefix");
				if (path == null)
					return string.Empty;

				return path;
			}
			set
			{
				if (LinkPrefix == value)
					return;

				m_settings.Set("FeedItemLinkPrefix", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// A list of possible prefixes so user can select one
		/// </summary>
		public static List<KeyValuePair<string, string>> LinkPrefixProviders
		{
			get
			{
				string providers = m_settings.Get("LinkPrefixProviders");
				if (providers == null)
				{
					providers = "Skweezer|http://www.skweezer.net/skweeze.aspx?i=1&q=|Google|http://www.google.com/gwt/n?u=";
					m_settings.Set("LinkPrefixProviders", providers);
					m_SettingsChanged = true;
				}

				var retval = new List<KeyValuePair<string, string>>();
				retval.Add(new KeyValuePair<string, string>("None", string.Empty));

				string[] data = providers.Split("|".ToCharArray());

				for (int i = 0; i < data.Length; i += 2)
				{
					if (i + 1 < data.Length)
					{
						retval.Add(new KeyValuePair<string, string>(data[i], data[i + 1]));
					}
				}

				return retval;
			}
		}

		/// <summary>
		/// Allows you to set a global hadler for all external URLS. (For example if you want to set a different browser for them)
		/// %1 in the handler will be replaced with the URL (for example iexplore %1)
		/// </summary>
		public static string ExternalUrlHandler
		{
			get
			{
				string path = m_settings.Get("ExternalUrlHandler");
				if (path == null)
					return string.Empty;

				return path;
			}
			set
			{
				if (ExternalUrlHandler == value)
					return;

				m_settings.Set("ExternalUrlHandler", value ?? string.Empty);
				m_SettingsChanged = true;
			}
		}


		/// <summary>
		/// Specifies the User Agent used when making HTTP requests for feeds
		/// </summary>
		public static string UserAgent
		{
			get
			{
				string path = m_settings.Get("UserAgent");
				if (path == null)
					return "Mozilla/4.0 (compatible; MSIE 6.0)";

				return path;
			}
			set
			{
				if (UserAgent == value)
					return;

				m_settings.Set("UserAgent", value ?? string.Empty);
				m_SettingsChanged = true;
			}
		}


		/// <summary>
		/// The height of the Player
		/// </summary>
		public static CoreHelper.PlayerView PlayerView
		{
			get
			{
				string value = m_settings.Get("PlayerView");

				// IH: 06-Sep-2006: value could be missing
				if (null == value)
					return CoreHelper.PlayerView.Small;

				try
				{
					return (CoreHelper.PlayerView) int.Parse(value);
				}
				catch (Exception ex)
				{
					Debug.WriteLine(ex);
					return CoreHelper.PlayerView.Small;
				}
			}
			set
			{
				if (PlayerView == value)
					return;

				m_settings.Set("PlayerView", ((int) value).ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The TraceLevel 0= none 
		/// </summary>
		public static int TraceLevel
		{
			get
			{
				string value = m_settings.Get("TraceLevel");

				// IH: 06-Sep-2006: value could be missing
				if (null == value)
					return 0;

				try
				{
					return int.Parse(value);
				}
				catch (Exception ex)
				{
					Debug.WriteLine(ex);
					return 0;
				}
			}
			set
			{
				if (LongSkipInterval == value)
					return;

				m_settings.Set("TraceLevel", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the feeds sort order.
		/// </summary>
		/// <value>The feeds sort order.</value>
		public static CoreHelper.SortOrder FeedsSortOrder
		{
			get
			{
				string value = m_settings.Get("FeedsSortOrder");

				// IH: 06-Sep-2006: value could be missing
				if (null == value)
					return CoreHelper.SortOrder.ByNameAsc;

				try
				{
					return (CoreHelper.SortOrder) int.Parse(value);
				}
				catch (Exception ex)
				{
					Debug.WriteLine(ex);
					return CoreHelper.SortOrder.ByNameAsc;
				}
			}
			set
			{
				if (FeedsSortOrder == value)
					return;

				m_settings.Set("FeedsSortOrder", ((int) value).ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the tracks sort order.
		/// </summary>
		/// <value>The feeds sort order.</value>
		public static CoreHelper.SortOrder TracksSortOrder
		{
			get
			{
				string value = m_settings.Get("TracksSortOrder");

				// IH: 06-Sep-2006: value could be missing
				if (null == value)
					return CoreHelper.SortOrder.ByNameAsc;

				try
				{
					return (CoreHelper.SortOrder) int.Parse(value);
				}
				catch (Exception ex)
				{
					Debug.WriteLine(ex);
					return CoreHelper.SortOrder.ByNameAsc;
				}
			}
			set
			{
				if (TracksSortOrder == value)
					return;

				m_settings.Set("TracksSortOrder", ((int) value).ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// The VolumeLevel
		/// </summary>
		public static int VolumeLevel
		{
			get
			{
				string value = m_settings.Get("VolumeLevel");
				try
				{
					return int.Parse(value);
				}
				catch
				{
					return 70;
				}
			}
			set
			{
				if (VolumeLevel == value)
					return;

				m_settings.Set("VolumeLevel", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the path to the Original skin tha
		/// </summary>
		public static string OriginalPlayerSkinPath
		{
			get
			{
				string path = m_settings.Get("OriginalPlayerSkin");
				if (path == null)
					return string.Empty;

				return path;
			}
			set
			{
				if (OriginalPlayerSkinPath == value)
					return;

				m_settings.Set("OriginalPlayerSkin", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the the default font size for the document
		/// </summary>
		public static string DefaultDocFontSize
		{
			get
			{
				string size = m_settings.Get("DocumentFontSize");
				if (size == null)
					return "medium";

				return size;
			}
			set
			{
				if (DefaultDocFontSize == value)
					return;

				m_settings.Set("DocumentFontSize", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the level for autocollapsing (in symbols)
		/// </summary>
		public static int AutoCollapseLevel
		{
			get
			{
				string lvl = m_settings.Get("AutoCollapse");
				try
				{
					return int.Parse(lvl);
				}
				catch
				{
					return 500; // never
				}
			}
			set
			{
				if (AutoCollapseLevel == value)
					return;

				m_settings.Set("AutoCollapse", value.ToString());
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets if the read items should be hidden in the feed
		/// </summary>
		public static bool HideReadItems
		{
			get
			{
				string value = m_settings.Get("HideReadItems");
				if (value == null)
					return false;

				return value == "1" ? true : false;
			}
			set
			{
				if (HideReadItems == value)
					return;

				m_settings.Set("HideReadItems", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Forces Update of all feeds on application startup
		/// </summary>
		public static bool UpdateOnStartup
		{
			get
			{
				string value = m_settings.Get("UpdateOnStartup");
				if (value == null)
					return false;

				return value == "1" ? true : false;
			}
			set
			{
				if (UpdateOnStartup == value)
					return;

				m_settings.Set("UpdateOnStartup", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Indicates id tracks have to be grouped by feed when showing "All Tracks in category"
		/// </summary>
		public static bool GroupByFeedIfShowingCategoryTracks
		{
			get
			{
				string value = m_settings.Get("GroupByFeedIfShowingCategoryTracks");
				if (value == null)
					return true;

				return value == "1" ? true : false;
			}
			set
			{
				if (GroupByFeedIfShowingCategoryTracks == value)
					return;

				m_settings.Set("GroupByFeedIfShowingCategoryTracks", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}


		/// <summary>
		/// Forces Update of the feed on open
		/// </summary>
		public static bool UpdateOnFeedOpen
		{
			get
			{
				string value = m_settings.Get("UpdateOnFeedOpen");
				if (value == null)
					return false;

				return value == "1" ? true : false;
			}
			set
			{
				if (UpdateOnFeedOpen == value)
					return;

				m_settings.Set("UpdateOnFeedOpen", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}


		/// <summary>
		/// 
		/// </summary>
		public static bool AllowAutoTrackDeletions
		{
			get
			{
				string value = m_settings.Get("AllowAutoTrackDeletions");
				if (value == null)
					return true;

				return value == "1" ? true : false;
			}
			set
			{
				if (AllowAutoTrackDeletions == value)
					return;

				m_settings.Set("AllowAutoTrackDeletions", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}


		/// <summary>
		/// Gets or sets the actively selected category
		/// </summary>
		public static FeedCategory ActiveFeedCategory
		{
			get
			{
				if (m_ActiveFeedCategory == null)
				{
					string category = m_settings.Get("ActiveCategory");
					if (string.IsNullOrEmpty(category))
						m_ActiveFeedCategory = CategoryManager.AllFeeds;
					else
					{
						FeedCategory c = CategoryManager.GetCategoryByValue(category);
						if (c == CategoryManager.CategoryNull)
							c = CategoryManager.AllFeeds;

						m_ActiveFeedCategory = c;
					}
				}

				return m_ActiveFeedCategory;
			}
			set
			{
				if (ActiveFeedCategory == value)
					return;

				m_ActiveFeedCategory = value;
				m_settings.Set("ActiveCategory", value.Value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the actively selected category
		/// </summary>
		public static string FeedCategories
		{
			get
			{
				string categories = m_settings.Get("FeedCategories");
				return string.IsNullOrEmpty(categories) ? "News|Technology|Entertainment|Software|Favorites|Podcast Directories" : categories;
			}
			set
			{
				if (FeedCategories == value)
					return;

				m_settings.Set("FeedCategories", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the Google Reader User Name
		/// </summary>
		public static string GoogleReaderUserName
		{
			get
			{
				string path = m_settings.Get("GoogleReaderUserName");
				return path ?? string.Empty;
			}
			set
			{
				if (GoogleReaderUserName == value)
					return;

				m_settings.Set("GoogleReaderUserName", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the Google Reader Password
		/// </summary>
		public static string GoogleReaderPassword
		{
			get
			{
				string path = m_settings.Get("GoogleReaderPassword");
				return path ?? string.Empty;
			}
			set
			{
				if (GoogleReaderPassword == value)
					return;

				m_settings.Set("GoogleReaderPassword", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Maximum number of unread items to be included in WhatIsNew aggregate
		/// </summary>
		public static int GlobalNumItemsToIncludeInWhatIsNew
		{
			get
			{
				if (!m_GlobalNumItemsToIncludeInWhatIsNew.HasValue)
				{
					try
					{
						m_GlobalNumItemsToIncludeInWhatIsNew = int.Parse(m_settings.Get("NumItemsToIncludeInWhatIsNew"));
					}
					catch
					{
						m_GlobalNumItemsToIncludeInWhatIsNew = 10;
					}
				}

				return m_GlobalNumItemsToIncludeInWhatIsNew.Value;
			}
			set
			{
				if (GlobalNumItemsToIncludeInWhatIsNew == value)
					return;

				m_settings.Set("NumItemsToIncludeInWhatIsNew", value.ToString());
				m_GlobalNumItemsToIncludeInWhatIsNew = value;
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Maximum number of enclosures to be downloaded fo a feed at one time
		/// </summary>
		public static int GlobalMaxEnclosuresToOneStepDownload
		{
			get
			{
				if (!m_GlobalMaxEnclosuresToOneStepDownload.HasValue)
				{
					try
					{
						m_GlobalMaxEnclosuresToOneStepDownload = int.Parse(m_settings.Get("maxDownload"));
					}
					catch
					{
						m_GlobalMaxEnclosuresToOneStepDownload = 3;
					}
				}

				return m_GlobalMaxEnclosuresToOneStepDownload.Value;
			}
			set
			{
				if (GlobalMaxEnclosuresToOneStepDownload == value)
					return;

				m_settings.Set("maxDownload", value.ToString());
				m_GlobalMaxEnclosuresToOneStepDownload = value;
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Maximum number of enclosures to be kept per feed (Spacesaver) 
		/// </summary>
		public static int GlobalMaxEnclosures
		{
			get
			{
				if (!m_GlobalMaxEnclosures.HasValue)
				{
					try
					{
						m_GlobalMaxEnclosures = int.Parse(m_settings.Get("maxTracks"));
					}
					catch
					{
						m_GlobalMaxEnclosures = 50;
					}
				}

				return m_GlobalMaxEnclosures.Value;
			}
			set
			{
				if (GlobalMaxEnclosures == value)
					return;

				m_settings.Set("maxTracks", value.ToString());
				m_GlobalMaxEnclosures = value;
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Maximum number of enclosures to be kept per feed (Spacesaver) 
		/// </summary>
		public static TimeSpan GlobalKeepEnclosuresDuration
		{
			get
			{
				if (!m_GlobalKeepEnclosuresDuration.HasValue)
				{
					try
					{
						m_GlobalKeepEnclosuresDuration = new TimeSpan(int.Parse(m_settings.Get("maxTrackAge")), 0, 0, 0);
					}
					catch
					{
						m_GlobalKeepEnclosuresDuration = new TimeSpan(999, 0, 0, 0);
					}
				}

				return m_GlobalKeepEnclosuresDuration.Value;
			}
			set
			{
				if (GlobalKeepEnclosuresDuration == value)
					return;

				m_settings.Set("maxTrackAge", ((int) value.TotalDays).ToString());
				m_GlobalKeepEnclosuresDuration = value;
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets the path to the TTS executable
		/// </summary>
		public static string TTSHandler
		{
			get
			{
				string path = m_settings.Get("TTSHandler");
				return path ?? string.Empty;
			}
			set
			{
				if (TTSHandler == value)
					return;

				m_settings.Set("TTSHandler", value);
				m_SettingsChanged = true;
			}
		}

		/// <summary>
		/// Gets or sets if the screen should be automatically turned off on playback
		/// </summary>
		public static bool AutoScreenOffOnPlayback
		{
			get
			{
				string value = m_settings.Get("AutoScreenOffOnPlayback");
				if (value == null)
					return false;

				return value == "1" ? true : false;
			}
			set
			{
				if (AutoScreenOffOnPlayback == value)
					return;

				m_settings.Set("AutoScreenOffOnPlayback", value ? "1" : "0");
				m_SettingsChanged = true;
			}
		}

		#region Default Browser Helpers

		/// <summary>
		/// Gets or sets the extension of the files used by BeyondPod.
		/// If user's device has mapped .htm extension to another browser (like Opera)
		/// BeyondPod will use a different extension. It also must add the correct
		/// mapping to the Registry (for example HKEY_CLASSES_ROOT\.bphtml
		/// </summary>
		public static string DocumentFileExtension
		{
			get { return IsUsingAlternateDocumentFileExtension ? AlternateDocumentFileExtension : DefaultDocumentFileExtension; }
		}

		public static string DefaultDocumentFileExtension
		{
			get { return "htm"; }
		}

		public static string AlternateDocumentFileExtension
		{
			get { return "bphtm"; }
		}

		public static bool IsUsingAlternateDocumentFileExtension
		{
			get
			{
				try
				{
					RegistryKey key = Registry.ClassesRoot.OpenSubKey("." + AlternateDocumentFileExtension);
					if (key != null)
					{
						key.Close();
						return true;
					}

					return false;
				}
				catch
				{
					return false;
				}
			}
		}

		public static bool IsHtmExtensionMappedCorrectly
		{
			get
			{
				try
				{
					string browser = GetDefaultBrowserCommandLine();

					if (string.IsNullOrEmpty(browser))
						return false;

					return browser.IndexOf("iexplore.exe", StringComparison.InvariantCultureIgnoreCase) != -1;
				}
				catch
				{
					return true;
				}
			}
		}

		public static string GetDefaultBrowserCommandLine()
		{
			RegistryKey htm = Registry.ClassesRoot.OpenSubKey(".htm");
			var value = htm.GetValue("", "") as string;

			if (string.IsNullOrEmpty(value))
				return null;

			return
				Registry.GetValue(string.Format(@"{0}\{1}\Shell\Open\Command", Registry.ClassesRoot.Name, value), "", "") as
				string;
		}

		public static string GetDefaultHttpHandlerCommandLine()
		{
			return
				Registry.GetValue(string.Format(@"{0}\{1}\Shell\Open\Command", Registry.ClassesRoot.Name, "http"), "", "") as
				string;
		}

		public static bool SwitchToAlternativeDocumentExtension()
		{
			try
			{
				CoreHelper.WriteLogEntry("Switching to Alternate Document Extension!...");

				RegistryKey file =
					Registry.ClassesRoot.CreateSubKey(AlternateDocumentFileExtension + @"file");

				RegistryKey shell = file.CreateSubKey("Shell");
				RegistryKey open = shell.CreateSubKey("Open");
				RegistryKey command = open.CreateSubKey("Command");

				command.SetValue("", "iexplore.exe file:%1", RegistryValueKind.String);
				file.Close();
				shell.Close();
				open.Close();
				command.Close();

				RegistryKey key = Registry.ClassesRoot.CreateSubKey("." + AlternateDocumentFileExtension);
				key.SetValue("", AlternateDocumentFileExtension + "file", RegistryValueKind.String);
				key.SetValue("Content Type", "text/html");
				key.Close();

				CoreHelper.WriteLogEntry("Switched to '." + DocumentFileExtension + "' extension!");
			}
			catch (Exception ex)
			{
				CoreHelper.WriteLogEntry("Unable to set Alternate Document Extension mappings in the registry! Reason:" + ex.Message);
				return false;
			}

			return true;
		}

		public static bool SwitchToDefaultDocumentExtension()
		{
			try
			{
				Registry.ClassesRoot.DeleteSubKeyTree(AlternateDocumentFileExtension + @"file\Shell\Open\Command");
				Registry.ClassesRoot.DeleteSubKeyTree("." + AlternateDocumentFileExtension);
			}
			catch (Exception ex)
			{
				CoreHelper.WriteLogEntry("Unable to clear the Alternate Document Extension to the registry! Reason:" + ex.Message);
				return false;
			}

			return true;
		}

		#endregion

		public static void SaveSettings()
		{
			if (!m_SettingsChanged)
				return;

			try
			{
				var tw = new XmlTextWriter(m_settingsPath,
				                           Encoding.UTF8);
				tw.WriteStartDocument();
				tw.WriteStartElement("configuration");
				tw.WriteStartElement("appSettings");

				for (int i = 0; i < m_settings.Count; ++i)
				{
					tw.WriteStartElement("add");
					tw.WriteAttributeString("key", m_settings.GetKey(i));
					tw.WriteAttributeString("value", m_settings.Get(i));
					tw.WriteEndElement();
				}

				tw.WriteEndElement();
				tw.WriteEndElement();

				tw.Close();
			}
			catch (Exception ex)
			{
				CoreHelper.WriteLogEntry("Unable to save the application seetings! Reason:" + ex.Message);
			}

			m_SettingsChanged = false;
		}
	}
}